本篇文章主要介绍 Spring 中是如何处理 @Autowired
注解的。
前言 我们平时使用 Spring 时,想要 依赖注入 时使用最多的是 @Autowired
注解了,本文主要讲解 Spring 是如何处理该注解并实现 依赖注入 的功能的。
正文 首先我们看一个测试用例:
User
实体类:
1 2 3 4 5 6 7 public class User { private Long id; private String name; }
测试类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 public class AnnotationDependencyInjectTest { @Autowired private User user; private City city; @Autowired public void initCity (City city) { this .city = city; } public static void main (String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.register(AnnotationDependencyInjectTest.class); context.refresh(); AnnotationDependencyInjectTest bean = context.getBean(AnnotationDependencyInjectTest.class); System.out.println(bean.user); System.out.println(bean.city); UserHolder userHolder = context.getBean(UserHolder.class); System.out.println(userHolder.getUser()); context.close(); } @Bean public User user () { User user = new User(); user.setId(1L ); user.setName("leisurexi" ); return user; } @Bean public City city () { City city = new City(); city.setId(1L ); city.setName("北京" ); return city; } static class UserHolder { private User user; @Autowired public UserHolder (User user) { this .user = user; } public User getUser () { return user; } public void setUser (User user) { this .user = user; } } }
上面分别展示了 @Autowired
注解的字段注入和方法注入,下面我们开始分析 Spring 是如何实现的。
首先使 @Autowired
注解生效的一个关键类是 AutowiredAnnotationBeanPostProcessor
,该类实现了 InstantiationAwareBeanPostProcessorAdapter
抽象类;该抽象类就是一个适配器的作用提供了接口方法的默认实现,InstantiationAwareBeanPostProcessorAdapter
又实现了 SmartInstantiationAwareBeanPostProcessor
接口,同时实现该接口的 determineCandidateConstructors()
方法可以指定 bean
的候选构造函数;然后 SmartInstantiationAwareBeanPostProcessor
接口又继承了 InstantiationAwareBeanPostProcessor
接口,该接口提供了 bean
实例化前后的生命周期回调以及属性赋值前的后置处理方法,@Autowired
注解的属性注入就是通过重写该接口的 postProcessProperties()
实现的。这两个接口都在 在 Spring IoC createBean 方法详解 一文中有介绍过。下面我们看一下 AutowiredAnnotationBeanProcessor
的继承关系图:
关于 AutowiredAnnotationBeanPostProcessor
这个后置处理器是怎么加入到 beanFactory
中的,我们在 Spring IoC component-scan 节点详解 一文中介绍过主要是通过 AnnotationConfigUtils#registerAnnotationConfigProcessors()
实现的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors ( BeanDefinitionRegistry registry, @Nullable Object source) { if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) { RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class); def.setSource(source); beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)); } }
属性和方法注入 AutowiredAnnotationBeanPostProcessor
中跟属性注入有关的方法有两个:postProcessMergedBeanDefinition
和 postProcessPropertyValues
。
前者是 MergedBeanDefinitionPostProcessor
接口中的方法,定义如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor { void postProcessMergedBeanDefinition (RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) ; default void resetBeanDefinition (String beanName) { } }
后者是 InstantiationAwareBeanPostProcessor
接口中的方法,定义如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor { @Nullable default Object postProcessBeforeInstantiation (Class<?> beanClass, String beanName) throws BeansException { return null ; } default boolean postProcessAfterInstantiation (Object bean, String beanName) throws BeansException { return true ; } @Nullable default PropertyValues postProcessProperties (PropertyValues pvs, Object bean, String beanName) throws BeansException { return null ; } @Deprecated @Nullable default PropertyValues postProcessPropertyValues ( PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException { return pvs; } }
关于这两个方法的调用时机,可以查看 Spring IoC createBean 方法详解 。
AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition 首先执行的是 postProcessMergedBeanDefinition()
。
1 2 3 4 5 6 public void postProcessMergedBeanDefinition (RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) { InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null ); metadata.checkConfigMembers(beanDefinition); }
InjectionMetadata
就是注入的元信息描述,主要字段如下:
1 2 3 4 5 6 7 8 9 10 public class InjectionMetadata { private final Class<?> targetClass; private final Collection<InjectedElement> injectedElements; }
InjectedElement
就是注入的元素,主要字段如下:
1 2 3 4 5 6 7 8 public abstract static class InjectedElement { protected final Member member; protected final boolean isField; }
AutowiredAnnotationBeanPostProcessor#findAutowiringMetadata 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 private InjectionMetadata findAutowiringMetadata (String beanName, Class<?> clazz, @Nullable PropertyValues pvs) { String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName()); InjectionMetadata metadata = this .injectionMetadataCache.get(cacheKey); if (InjectionMetadata.needsRefresh(metadata, clazz)) { synchronized (this .injectionMetadataCache) { metadata = this .injectionMetadataCache.get(cacheKey); if (InjectionMetadata.needsRefresh(metadata, clazz)) { if (metadata != null ) { metadata.clear(pvs); } metadata = buildAutowiringMetadata(clazz); this .injectionMetadataCache.put(cacheKey, metadata); } } } return metadata; }
AutowiredAnnotationBeanPostProcessor#buildAutowiringMetadata 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 private InjectionMetadata buildAutowiringMetadata (final Class<?> clazz) { if (!AnnotationUtils.isCandidateClass(clazz, this .autowiredAnnotationTypes)) { return InjectionMetadata.EMPTY; } List<InjectionMetadata.InjectedElement> elements = new ArrayList<>(); Class<?> targetClass = clazz; do { final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>(); ReflectionUtils.doWithLocalFields(targetClass, field -> { MergedAnnotation<?> ann = findAutowiredAnnotation(field); if (ann != null ) { if (Modifier.isStatic(field.getModifiers())) { if (logger.isInfoEnabled()) { logger.info("Autowired annotation is not supported on static fields: " + field); } return ; } boolean required = determineRequiredStatus(ann); currElements.add(new AutowiredFieldElement(field, required)); } }); ReflectionUtils.doWithLocalMethods(targetClass, method -> { Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) { return ; } MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod); if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) { if (Modifier.isStatic(method.getModifiers())) { if (logger.isInfoEnabled()) { logger.info("Autowired annotation is not supported on static methods: " + method); } return ; } if (method.getParameterCount() == 0 ) { if (logger.isInfoEnabled()) { logger.info("Autowired annotation should only be used on methods with parameters: " + method); } } boolean required = determineRequiredStatus(ann); PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz); currElements.add(new AutowiredMethodElement(method, required, pd)); } }); elements.addAll(0 , currElements); targetClass = targetClass.getSuperclass(); } while (targetClass != null && targetClass != Object.class); return InjectionMetadata.forElements(elements, clazz); }
上面代码中的 findAutowiredAnnotation()
就是在遍历 autowiredAnnotationTypes
属性,看字段或者方法上的注解是否存在于 autowiredAnnotationTypes
中,或者其派生注解,找到第一个就返回,不会再继续遍历了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter implements MergedBeanDefinitionPostProcessor , PriorityOrdered , BeanFactoryAware { private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(4 ); public AutowiredAnnotationBeanPostProcessor () { this .autowiredAnnotationTypes.add(Autowired.class); this .autowiredAnnotationTypes.add(Value.class); try { this .autowiredAnnotationTypes.add((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Inject" , AutowiredAnnotationBeanPostProcessor.class.getClassLoader())); logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring" ); } catch (ClassNotFoundException ex) { } } }
从 AutowiredAnnotationBeanPostProcessor
类的构造函数中,我们可以发现 autowiredAnnotationTypes
默认添加了 @Autowired
、@Value
以及 @Inject
(在 JSR-330 的jar包存在于当前环境时)。
至此,使用 @Autowired
修饰的字段和方法已经封装成 InjectionMetadata
并放在 injectionMetadataCache
缓存中,便于后续使用。
AutowireAnnotationBeanPostProcessor#postProcessProperties postProcessMergedBeanDefinition()
调用后 bean
就会进行实例化接着调用 postProcessProperties()
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 public PropertyValues postProcessProperties (PropertyValues pvs, Object bean, String beanName) { InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs); try { metadata.inject(bean, beanName, pvs); } catch (BeanCreationException ex) { throw ex; } catch (Throwable ex) { throw new BeanCreationException(beanName, "Injection of autowired dependencies failed" , ex); } return pvs; } public void inject (Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { Collection<InjectedElement> checkedElements = this .checkedElements; Collection<InjectedElement> elementsToIterate = (checkedElements != null ? checkedElements : this .injectedElements); if (!elementsToIterate.isEmpty()) { for (InjectedElement element : elementsToIterate) { if (logger.isTraceEnabled()) { logger.trace("Processing injected element of bean '" + beanName + "': " + element); } element.inject(target, beanName, pvs); } } }
AutowiredFieldElement#inject 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 protected void inject (Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { Field field = (Field) this .member; Object value; if (this .cached) { value = resolvedCachedArgument(beanName, this .cachedFieldValue); } else { DependencyDescriptor desc = new DependencyDescriptor(field, this .required); desc.setContainingClass(bean.getClass()); Set<String> autowiredBeanNames = new LinkedHashSet<>(1 ); Assert.state(beanFactory != null , "No BeanFactory available" ); TypeConverter typeConverter = beanFactory.getTypeConverter(); try { value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter); } catch (BeansException ex) { throw new UnsatisfiedDependencyException(null , beanName, new InjectionPoint(field), ex); } synchronized (this ) { if (!this .cached) { if (value != null || this .required) { this .cachedFieldValue = desc; registerDependentBeans(beanName, autowiredBeanNames); if (autowiredBeanNames.size() == 1 ) { String autowiredBeanName = autowiredBeanNames.iterator().next(); if (beanFactory.containsBean(autowiredBeanName) && beanFactory.isTypeMatch(autowiredBeanName, field.getType())) { this .cachedFieldValue = new ShortcutDependencyDescriptor( desc, autowiredBeanName, field.getType()); } } } else { this .cachedFieldValue = null ; } this .cached = true ; } } } if (value != null ) { ReflectionUtils.makeAccessible(field); field.set(bean, value); } }
上面代码中的 beanFactory.resolveDependency()
在 Spring IoC createBean 方法详解 一文中有介绍过,这里不再赘述;同样 registerDependentBeans()
最终会调用 DefaultSingletonBeanRegistry.registerDependentBean()
,该方法在 Spring IoC getBean 方法详解 一文中有介绍过,这里也不再赘述。
AutowiredMethodElement#inject 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 protected void inject (Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { if (checkPropertySkipping(pvs)) { return ; } Method method = (Method) this .member; Object[] arguments; if (this .cached) { arguments = resolveCachedArguments(beanName); } else { int argumentCount = method.getParameterCount(); arguments = new Object[argumentCount]; DependencyDescriptor[] descriptors = new DependencyDescriptor[argumentCount]; Set<String> autowiredBeans = new LinkedHashSet<>(argumentCount); Assert.state(beanFactory != null , "No BeanFactory available" ); TypeConverter typeConverter = beanFactory.getTypeConverter(); for (int i = 0 ; i < arguments.length; i++) { MethodParameter methodParam = new MethodParameter(method, i); DependencyDescriptor currDesc = new DependencyDescriptor(methodParam, this .required); currDesc.setContainingClass(bean.getClass()); descriptors[i] = currDesc; try { Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter); if (arg == null && !this .required) { arguments = null ; break ; } arguments[i] = arg; } catch (BeansException ex) { throw new UnsatisfiedDependencyException(null , beanName, new InjectionPoint(methodParam), ex); } } synchronized (this ) { if (!this .cached) { if (arguments != null ) { DependencyDescriptor[] cachedMethodArguments = Arrays.copyOf(descriptors, arguments.length); registerDependentBeans(beanName, autowiredBeans); if (autowiredBeans.size() == argumentCount) { Iterator<String> it = autowiredBeans.iterator(); Class<?>[] paramTypes = method.getParameterTypes(); for (int i = 0 ; i < paramTypes.length; i++) { String autowiredBeanName = it.next(); if (beanFactory.containsBean(autowiredBeanName) && beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) { cachedMethodArguments[i] = new ShortcutDependencyDescriptor(descriptors[i], autowiredBeanName, paramTypes[i]); } } } this .cachedMethodArguments = cachedMethodArguments; } else { this .cachedMethodArguments = null ; } this .cached = true ; } } } if (arguments != null ) { try { ReflectionUtils.makeAccessible(method); method.invoke(bean, arguments); } catch (InvocationTargetException ex) { throw ex.getTargetException(); } } }
构造器注入 构造器注入就是通过调用 determineCandidateConstructors()
来返回合适的构造器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName) throws BeanCreationException { Constructor<?>[] candidateConstructors = this .candidateConstructorsCache.get(beanClass); if (candidateConstructors == null ) { synchronized (this .candidateConstructorsCache) { candidateConstructors = this .candidateConstructorsCache.get(beanClass); if (candidateConstructors == null ) { Constructor<?>[] rawCandidates; try { rawCandidates = beanClass.getDeclaredConstructors(); } catch (Throwable ex) { throw new BeanCreationException(beanName, "Resolution of declared constructors on bean Class [" + beanClass.getName() +"] from ClassLoader [" + beanClass.getClassLoader() + "] failed" , ex); } List<Constructor<?>> candidates = new ArrayList<>(rawCandidates.length); Constructor<?> requiredConstructor = null ; Constructor<?> defaultConstructor = null ; for (Constructor<?> candidate : rawCandidates) { MergedAnnotation<?> ann = findAutowiredAnnotation(candidate); if (ann == null ) { Class<?> userClass = ClassUtils.getUserClass(beanClass); if (userClass != beanClass) { try { Constructor<?> superCtor = userClass.getDeclaredConstructor(candidate.getParameterTypes()); ann = findAutowiredAnnotation(superCtor); } catch (NoSuchMethodException ex) { } } } if (ann != null ) { if (requiredConstructor != null ) { throw new BeanCreationException(beanName, "Invalid autowire-marked constructor: " + candidate +". Found constructor with 'required' Autowired annotation already: " + requiredConstructor); } boolean required = determineRequiredStatus(ann); if (required) { if (!candidates.isEmpty()) { throw new BeanCreationException(beanName,"Invalid autowire-marked constructors: " + candidates +". Found constructor with 'required' Autowired annotation: " + candidate); } requiredConstructor = candidate; } candidates.add(candidate); } else if (candidate.getParameterCount() == 0 ) { defaultConstructor = candidate; } } if (!candidates.isEmpty()) { if (requiredConstructor == null ) { if (defaultConstructor != null ) { candidates.add(defaultConstructor); } } candidateConstructors = candidates.toArray(new Constructor<?>[0 ]); } else if (rawCandidates.length == 1 && rawCandidates[0 ].getParameterCount() > 0 ) { candidateConstructors = new Constructor<?>[] {rawCandidates[0 ]}; } else if (nonSyntheticConstructors == 2 && primaryConstructor != null && defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) { candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor}; } else if (nonSyntheticConstructors == 1 && primaryConstructor != null ) { candidateConstructors = new Constructor<?>[] {primaryConstructor}; } else { candidateConstructors = new Constructor<?>[0 ]; } this .candidateConstructorsCache.put(beanClass, candidateConstructors); } } } return (candidateConstructors.length > 0 ? candidateConstructors : null ); }
关于 SmartInstantiationAwareBeanPostProcessor
接口的调用时机,在 Spring IoC createBean 方法详解 一文中有介绍过,这里就不再赘述了。
总结 本文主要介绍了 Spring 对 @Autowired
注解的主要处理过程,结合前面的 Spring IoC getBean 方法详解 和 Spring IoC createBean 方法详解 文章一起看才能更好的理解。
最后,我模仿 Spring 写了一个精简版,代码会持续更新。地址:https://github.com/leisurexi/tiny-spring 。访问新博客地址,观看效果更佳 https://leisurexi.github.io/